<template>
  <div class="container">
    <div class="content">
      <h1>{{ formState.dish.id ? '编辑' : '添加' }}店铺菜品</h1>
      <el-form
        :inline="true"
        :model="formState.dish"
        :rules="rules"
        ref="formRef"
        class="demo-form-inline"
        :label-position="'right'"
        label-width="120px"
      >
        <el-form-item label="菜品名称：" prop="name">
          <el-input v-model="formState.dish.name" placeholder="请输入菜品名称..." clearable class="input" />
        </el-form-item>
        <el-form-item label="分类类型：" prop="dishCategoryId">
          <el-select v-model="formState.dish.dishCategoryId" placeholder="请选择分类" class="select">
            <el-option
              v-for="(dishCategory, index) in formDataProvide.shopDishCategoryList"
              :key="index"
              :label="dishCategory.name"
              :value="dishCategory.id"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="菜品现价¥：" prop="nowPrice">
          <el-input-number :controls="false" :precision="2" v-model="formState.dish.nowPrice" placeholder="请输入现价" class="input" clearable />
        </el-form-item>
        <el-form-item label="菜品原价¥：">
          <el-input-number :controls="false" :precision="2" v-model="formState.dish.oldPrice" placeholder="请输入原价" class="input" clearable />
        </el-form-item>
        <el-form-item label="口味做法配置：" class="selfInLine">
          <div class="dishFlavor">
            <div>
              <div class="dishFlavorItem" v-for="(flavor, index) in formState.dishFlavors" :key="index">
                <span class="sortControl">
                  <el-button :icon="ArrowUpBold" :link="true" size="small" circle @click="adjustFlavorRanking(index, 1)" />
                  <el-button :icon="ArrowDownBold" :link="true" size="small" circle @click="adjustFlavorRanking(index, -1)" />
                </span>
                <SelectInput
                  class="dishFlavorName"
                  v-model="flavor.name"
                  :option-data="formDataProvide.selectableDishFlavors"
                  label="name"
                  :debounce-input="true"
                  @input="toSearchDishFlavor"
                  @select="(_option, _index) => clickDisFlavorOption(_option, _index, flavor)"
                />
                <el-select
                  class="dishFlavorValue"
                  multiple
                  filterable
                  allow-create
                  default-first-option
                  :reserve-keyword="false"
                  placeholder="可供选择的口味项"
                  :model-value="flavor.value == null || flavor.value === '' ? [] : flavor.value.split(',')"
                  @update:model-value="(flavors) => (flavor.value = flavors.join(','))"
                >
                  <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
                </el-select>
                <el-button type="warning" :link="true" class="deleteDishFlavorButton" @click="formState.dishFlavors.splice(index, 1)">删除</el-button>
              </div>
            </div>
            <el-button :icon="Plus" @click="addDishFlavor" :link="true" type="primary">添加口味</el-button>
          </div>
        </el-form-item>
        <el-form-item label="菜品图片：" class="selfInLine" prop="image">
          <oss-upload v-model="formState.dish.image" style="padding: 20px 0; width: 100%" :custom="true">
            <template v-slot:custom="{ listData, select }">
              <div class="imgShow">
                <img v-if="listData == null || listData.length === 0" src="@/assets/image/dish.png" />
                <img v-for="(url, index) in listData" :key="index" :src="url" style="height: 170px" />
                <div>
                  <p style="font-size: 10px; color: #787878">图片分辨率建议在200 x 200, 大小不能超过1M!</p>
                  <el-button :link="true" type="primary" @click="select"> 点击上传 </el-button>
                </div>
              </div>
            </template>
          </oss-upload>
        </el-form-item>
        <el-form-item label="菜品标签：" class="selfInLine">
          <el-select
            multiple
            filterable
            allow-create
            default-first-option
            :reserve-keyword="false"
            placeholder="输入内容并回车添加标签"
            class="labelInput"
            :model-value="formState.dish.labels == null || formState.dish.labels === '' ? [] : formState.dish.labels.split(',')"
            @update:model-value="(labels) => (formState.dish.labels = labels.join(','))"
          >
            <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
          </el-select>
        </el-form-item>
        <div class="control">
          <el-button size="large" @click="cancelToBack">取消</el-button>
          <el-button size="large" class="baseBut" @click="save">保存</el-button>
        </div>
      </el-form>
    </div>
  </div>
</template>

<script setup lang="ts">
import Dish from '@/types/entity/Dish'
import ossUpload from '@/components/oss-upload/index.vue'
import { reactive, ref, getCurrentInstance, watch } from 'vue'
import { Delete, Edit, Plus, Search, ArrowDownBold, ArrowUpBold } from '@element-plus/icons-vue'
import router from '@/router'
import ComponentHat from '@/plugins/type'
import DishCategory from '@/types/entity/DishCategory'
import DishFlavor from '@/types/entity/DishFlavor'
import SelectInput from '@/components/select-input/index.vue'
import propertiesCopyUtils from '@/utils/properties-copy'
import { DishSaveParam } from '@/types/param/dish'
import { useRoute } from 'vue-router'
import { FormRules } from 'element-plus'
const { $store, $API, $modal } = <ComponentHat>getCurrentInstance().proxy
const formRef = ref() // 表单引用
const options = ref([])
const formState = reactive({
  dish: new Dish(),
  dishFlavors: [] as DishFlavor[]
})

const formDataProvide = reactive({
  // 店铺分类数据
  shopDishCategoryList: [] as DishCategory[],
  selectableDishFlavors: [] as DishFlavor[]
})
// 表彰检验
const validatePrice = (rule: any, value: number, callback: any): void => {
  console.log(rule, value, callback)
  if (value == null) {
    callback(new Error('请输入价格'))
  } else if (value < 0) {
    callback(new Error('价格必须是正整数！'))
  } else {
    callback()
  }
}
const validateImage = (rule: any, value: string, callback: any): void => {
  if (!/https?:\/\/.+/.test(value)) {
    callback(new Error('这不是一个url值！请上传图片'))
  } else {
    callback()
  }
}
const rules = ref<FormRules>({
  name: [{ required: true, message: '菜品名称不能为空' }],
  dishCategoryId: [{ required: true, message: '菜品分类不能为空' }],
  nowPrice: [{ trigger: ['blur'], validator: validatePrice }],
  image: [
    { required: true, message: '需要一张菜品图片作为封面' },
    { trigger: ['change'], validator: validateImage }
  ]
})
// 如果传入id，获取数据回显
const route = useRoute()
const idParam = route.query.id as string
if (idParam != null) {
  $API.dish.getShopDishInfo(parseInt(idParam)).then((result) => {
    if (result.success) {
      propertiesCopyUtils([result.data], formState.dish)
      formState.dishFlavors = result.data.flavors
      console.log('回显:', formState)
    }
  })
}
// 监听dishFlavors，对里面的内容进行重排序
watch(
  () => formState.dishFlavors,
  (newDishFlavors) => {
    // 维护排序
    newDishFlavors.forEach((item, index) => (item.sort = index))
  },
  { deep: true, immediate: true }
)

// 初始化店铺分类数据
$API.dishCategory.listShopDishCategory().then((result) => {
  formDataProvide.shopDishCategoryList = result.data
})
// 点击了取消按钮返回上一层
function cancelToBack() {
  router.back()
}
// 点击添加口味
function addDishFlavor() {
  formState.dishFlavors.push(new DishFlavor())
}
// 去搜索口味
async function toSearchDishFlavor(keyword: string) {
  // 去更新口味项数据
  // 默认只显示4条
  const result = await $API.dishFlavor.selectShopDishFlavor(keyword, 4)
  if (result.success) {
    formDataProvide.selectableDishFlavors = result.data
  }
}
// 点击了菜品口味
function clickDisFlavorOption(_option: DishFlavor, index: number, item: DishFlavor) {
  item.value = _option.value
}
// 口味项UP / DOWN
function adjustFlavorRanking(flavorIndex: number, digitCount: number) {
  const flavors = formState.dishFlavors
  // 忽略不合理的操作
  if (digitCount === 0 || (flavorIndex === 0 && digitCount > 0) || (flavorIndex === flavors.length - 1 && digitCount < 0)) return
  // 可移动
  const targetIndex: number = flavorIndex - digitCount
  const temp: DishFlavor = flavors[flavorIndex]
  flavors[flavorIndex] = flavors[targetIndex]
  flavors[targetIndex] = temp
}
// 点击了保存
function save() {
  formRef.value.validate(async (valid: boolean) => {
    if (!valid) {
      $modal.msgError('请填写表单中的必填项！')
      return
    }
    const result = await $API.dish.saveShopDish({ ...formState.dish, flavors: formState.dishFlavors })
    if (result.success) {
      $modal.msgSuccess('保存菜品成功！')
      router.push('/dish')
    } else {
      $modal.msgError('保存菜品失败！' + result.message)
    }
  })
}
</script>

<style scoped lang="scss">
.container {
  overflow: auto;
  width: 100%;
  height: 100%;
  background-color: #f5f5f5;
  box-sizing: border-box;
}

.content {
  display: flex;
  align-items: center;
  margin: 3%;
  padding: 30px 11%;
  background-color: #fff;
  box-sizing: content-box;
  flex-direction: column;

  h1 {
    margin-bottom: 30px;
    font-size: 22px;
    color: #545c64;
  }

  .select,
  .input {
    width: 200px;
  }

  .labelInput {
    width: 100%;
  }

  .control {
    display: flex;
    justify-content: center;
    margin-top: 30px;
  }

  .imgShow {
    display: flex;
    justify-content: start;
    align-items: center;
    width: 100%;

    div {
      margin: 0 auto;
    }
  }

  .dishFlavor {
    padding: 15px 30px;
    width: 100%;
    border: 1px solid #fafafa;
    border-radius: 3px;
    background-color: #fafafa;
    box-sizing: border-box;

    .dishFlavorItem {
      display: flex;
      justify-content: left;
      margin: 5px 0;
      width: 100%;
      flex-wrap: nowrap;

      .dishFlavorName {
        margin-right: 15px;
        max-width: 150px;
      }

      .dishFlavorValue {
        margin-right: 15px;
        width: 0;
        flex-grow: 1;
      }
    }
  }
}

.inline {
  display: inline;
}

.selfInLine {
  display: flex;
  justify-content: start;
}

.sortControl {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: left;
  margin-right: 2px;

  * {
    margin: 0;
    height: 13px;
    box-sizing: border-box;
  }
}
</style>
